package com.ruoyi.AI.controller;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.AI.domain.AiDto;
import com.ruoyi.AI.service.AiService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.ollama.OllamaChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * @author songsir
 * @date 2021/6/4
 **/
@Slf4j
@RestController
@CrossOrigin
@RequestMapping({"/ai/chat"})
@RequiredArgsConstructor
@Api(tags = "AI接口")
public class AiController {

    @Autowired(required = true)
    private OllamaChatModel ollamaChatModel;

    @Autowired
    private AiService aiService;

    //@Autowired
    // private OpenAiChatModel openAiChatModel;

    @Autowired(required = false)
    private ChatClient chatClient;

    @ApiOperation("简单调用")
    @PostMapping(value = "/ask", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Object ask(@RequestBody AiDto dto) {
        return chatClient.prompt(dto.getMsg());
    }


    @ApiOperation("流式调用")
    @PostMapping(value = "/ask/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> stream(@RequestBody AiDto dto) {
        System.out.println(ollamaChatModel);
        return ollamaChatModel.stream(dto.getMsg());
    }

    @ApiOperation("分析上下文聊天")
    @PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Object chat(@RequestBody AiDto dto) {
        return aiService.chat(dto.getMsg());
    }

    @ApiOperation("流式上下文聊天")
    @PostMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chatStream(@RequestBody AiDto dto) {

        return aiService.chatStream(dto.getMsg());
    }

    @ApiOperation("AI聊天")
    @PostMapping(value = "/chat/python", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public ResponseEntity<String> getTextResponseEntity(@RequestBody AiDto dto) {
        String url = "http://localhost:5000/api/stream"; // 替换为你的服务地址
        String message = dto.getMsg(); // 要发送的消息

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url + "?message=" + message))
                .build();

        try {
            HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());

            if (response.statusCode() == 200) {
                /*InputStream inputStream = response.body();
                int singleByte;
                while ((singleByte = inputStream.read()) != -1) {
                    System.out.print(String.valueOf((char) singleByte)); // 输出字符
                }*/
                InputStream inputStream = response.body();
                InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8"); // 指定字符编码
                int singleByte;
                while ((singleByte = reader.read()) != -1) {
                    System.out.print(String.valueOf((char) singleByte)); // 应该正确显示字符
                    return ResponseEntity.ok(String.valueOf((char) singleByte));
                }
            } else {
                System.out.println("Failed to connect to the API with status code: " + response.statusCode());
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @ApiOperation("AI聊天2")
    @PostMapping(value = "/chat/python2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public ResponseBodyEmitter getResponseEntity(@RequestBody AiDto dto) {
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();
        String message = dto.getMsg(); // 要发送的消息
        String apiUrl = "http://localhost:5000/api/stream"; // 替换为你的服务地址

        // 启动一个新的线程来处理数据流
        new Thread(() -> {
            try {
                URL url = new URL(apiUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("content-Type", "application/json");
                connection.setDoOutput(true);
                connection.setDoInput(true);

                Map<String, Object> sendMap = new HashMap<>();
                sendMap.put("message", message);
                JSONObject jsonobject = new JSONObject(sendMap);
                String sl = jsonobject.toString();
                byte[] bytes = sl.getBytes();
                DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
                wr.write(bytes);
                wr.close();
                // 获取输入流，这里是获取返回的数据流
                InputStream inputStream = connection.getInputStream();

                // 处理输入流，这里可以根据需要进行流式处理
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null) {
                    // 发送每行数据给客户端
                    try {
                        System.out.println(line);
                        emitter.send(line, MediaType.TEXT_PLAIN);
                    } catch (IOException e) {
                        e.printStackTrace();
                        // 处理发送异常，比如客户端断开连接

                        break;
                    }
                }
                // 关闭资源
                reader.close();

                // 获取响应码，根据需要处理
                int responseCode = connection.getResponseCode();
                System.out.println("Response Code:" + responseCode);
                // 断开连接
                connection.disconnect();
                // 发送完成信号
                emitter.complete();

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
                // 发送错误信号
                emitter.completeWithError(e);
            }
        }).start();
        return emitter;
    }

    @ApiOperation("AI聊天3")
    @PostMapping(value = "/chat/python3", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public StringBuilder doPost(@RequestBody AiDto dto) {
        String sendUrl = "http://localhost:5000/api/stream";
        Map<String, Object> sendMap = new HashMap<>();
        sendMap.put("message", dto.getMsg());
        StringBuilder response = new StringBuilder();

        try {
            URL url = new URL(sendUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("content-Type", "application/json");
            connection.setDoOutput(true);
            connection.setDoInput(true);
            JSONObject jsonobject = new JSONObject(sendMap);
            String sl = jsonobject.toString();
            byte[] bytes = sl.getBytes();
            DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
            wr.write(bytes);
            wr.close();
            int statusCode = connection.getResponseCode();
            InputStream inputStream = statusCode == 200 ? connection.getInputStream() : connection.getErrorStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
                System.out.println(line);
            }
            reader.close();
            inputStream.close();
            connection.disconnect();
        } catch (Exception e) {
            log.error("发送post请求异常:" + e);
            e.printStackTrace();

        }
        return response;
    }

    private final ExecutorService executor = Executors.newCachedThreadPool();

    @ApiOperation("AI聊天4")
    @PostMapping(value = "/chat/python4", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter doPost4(@RequestBody AiDto dto) {
        SseEmitter emitter = new SseEmitter();
        String sendUrl = "http://localhost:5000/api/stream";
        Map<String, Object> sendMap = new HashMap<>();
        sendMap.put("message", dto.getMsg());

        new Thread(() -> {

            try {
                URL url = new URL(sendUrl);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setDoOutput(true);
                JSONObject jsonobject = new JSONObject(sendMap);
                byte[] bytes = jsonobject.toString().getBytes("utf-8");
                try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) {
                    wr.write(bytes);
                }

                InputStream inputStream = connection.getResponseCode() == 200 ? connection.getInputStream() : connection.getErrorStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));

                String line;
                while ((line = reader.readLine()) != null) {
                    // 将每行内容逐字发送给前端
                    for (char c : line.toCharArray()) {
                        SseEmitter.SseEventBuilder event = SseEmitter.event()
                                .data(String.valueOf(c));
                        emitter.send(event);
                        System.out.print(String.valueOf(c));
                    }
                    // 可以考虑在这里添加一个短暂的延迟，以便用户能看清逐字输出的效果
                    Thread.sleep(10); // 注意：在生产环境中可能需要更复杂的流控逻辑
                }
                reader.close();
                connection.disconnect();
                emitter.complete();
            } catch (Exception e) {
                log.error("发送post请求异常:" + e);
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }

    // private final WebClient webClient;


    @ApiOperation("AI聊天5")
    @PostMapping(value = "/chat/python5", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> proxyStream(@RequestBody AiDto dto) {
        WebClient webClient = WebClient.builder().baseUrl("http://localhost:5000/api/stream").build();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        return webClient.post()
                .uri(uriBuilder -> uriBuilder.build())
                .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .bodyValue("{\"message\": \"" + dto.getMsg() + "\"}")
                .retrieve()
                .bodyToFlux(String.class)
                .flatMap(chunk -> Flux.fromArray(chunk.split("")));
    }

    public static void main(String[] args) {
        String url = "http://localhost:5000/api/stream"; // 替换为你的服务地址
        String message = "请帮我写一首诗"; // 要发送的消息

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url + "?message=" + message))
                .build();

        try {
            HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());

            if (response.statusCode() == 200) {
                /*InputStream inputStream = response.body();
                int singleByte;
                while ((singleByte = inputStream.read()) != -1) {
                    System.out.print(String.valueOf((char) singleByte)); // 输出字符
                }*/
                InputStream inputStream = response.body();
                InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8"); // 指定字符编码
                int singleByte;
                while ((singleByte = reader.read()) != -1) {
                    System.out.print(String.valueOf((char) singleByte)); // 应该正确显示字符
                }
            } else {
                System.out.println("Failed to connect to the API with status code: " + response.statusCode());
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}
